package yns.utility;

import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;

import org.bson.Document;

import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;

public class MongoHelp {
	private static  List<ServerAddress> serverAddressList = new ArrayList<ServerAddress>();
	private static MongoClient mongoClient = null;
	
    private MongoHelp(){
    	
    }
    
	public static MongoClient getInstance() {
		if (mongoClient == null) {
			synchronized (MongoClient.class) {
				if (mongoClient == null) {
					try {
						getServerAddress();
						
						int connectionsPerHost = Integer.parseInt(UtilityProperties.getSystemValue("connectionsPerHost"));
						int ConnectionMultiplier = Integer.parseInt(UtilityProperties.getSystemValue("ConnectionMultiplier"));
						int maxWaitTime = Integer.parseInt(UtilityProperties.getSystemValue("maxWaitTime"));
						int connectTimeout = Integer.parseInt(UtilityProperties.getSystemValue("connectTimeout"));
						int maxConnectionIdleTime = Integer.parseInt(UtilityProperties.getSystemValue("maxConnectionIdleTime"));
						
						MongoClientOptions.Builder build = new MongoClientOptions.Builder();

						// 与目标数据库能够建立的最大connection数量
						build.connectionsPerHost(connectionsPerHost);
						// 如果当前所有的connection都在使用中，则每个connection上可以有多少个线程排队等待
						build.threadsAllowedToBlockForConnectionMultiplier(ConnectionMultiplier);
						// 一个线程访问数据库的时候，在成功获取到一个可用数据库连接之前的最长等待时间
						// 这里比较危险，如果超过maxWaitTime都没有获取到这个连接的话，该线程就会抛出Exception
						// 故这里设置的maxWaitTime应该足够大，以免由于排队线程过多造成的数据库访问失败
						build.maxWaitTime(maxWaitTime);
						// 与数据库建立连接的timeout
						build.connectTimeout(connectTimeout);
						// 空闲时间
						build.maxConnectionIdleTime(maxConnectionIdleTime);
					
						MongoClientOptions mongoClientOptions = build.build();
						System.out.println("mongo");
						
						List<MongoCredential> mongoCredentialList = getMongoCredentialList();
						MongoCredential mongoCredential = getMongoCredential();
						
						if (mongoCredentialList != null) {
							System.out.println("MongoCredentialList");
							mongoClient = new MongoClient(serverAddressList, mongoCredentialList, mongoClientOptions);
						} else if (mongoCredential != null) {
							mongoClient = new MongoClient(serverAddressList, mongoCredential, mongoClientOptions);
						} else {
							mongoClient = new MongoClient(serverAddressList, mongoClientOptions);
						}
						
					} catch (UnknownHostException e) {
						e.printStackTrace();
					}

				}
			}
		}
		return mongoClient;
	}
	
	public static MongoDatabase getMongoDb(String dbName){
		return getInstance().getDatabase(dbName);
	}
	
	public static MongoCollection<Document> getMongoCollection(String dbName,String collectionName){
		MongoDatabase db = getInstance().getDatabase(dbName);
		
		return db.getCollection(collectionName);
	}
	
	public static void close(){
		getInstance().close();
	}
	
	private static List<MongoCredential> getMongoCredentialList() {
		String userName = UtilityProperties.getSystemValue("mongoUserName");
		String database = UtilityProperties.getSystemValue("mongoDatabase");
		String password = UtilityProperties.getSystemValue("mongoPassword");
		
		if (userName == null || userName.equals("")) {
			return null;
		}
		if (database == null || database.equals("")) {
			return null;
		}
		if (password == null || password.equals("")) {
			return null;
		}
		
		
		MongoCredential credential = MongoCredential.createMongoCRCredential(userName, database, password.toCharArray());
		List<MongoCredential> mongoCredentialList = new ArrayList<MongoCredential>();
		mongoCredentialList.add(credential);
		
		return mongoCredentialList;
	}
	
	private static MongoCredential getMongoCredential() {
		String userName = UtilityProperties.getSystemValue("mongoUserName");
		String database = UtilityProperties.getSystemValue("mongoDatabase");
		String password = UtilityProperties.getSystemValue("mongoPassword");
		
		if (userName == null || userName.equals("")) {
			return null;
		}
		if (database == null || database.equals("")) {
			return null;
		}
		if (password == null || password.equals("")) {
			return null;
		}
		
		
		MongoCredential credential = MongoCredential.createMongoCRCredential(userName, database, password.toCharArray());
		
		return credential;
	}
	
	private static void getServerAddress() throws UnknownHostException{
		String propServerAddress = UtilityProperties.getSystemValue("MongoServerAddress");
		String[] propServerList = propServerAddress.split(";");
		
		ServerAddress serverAddress;
		for (int i = 0; i < propServerList.length; i++) {
			String eachServer = propServerList[i];
			
			String[] serverInfo = eachServer.split(":");
		 	serverAddress = new ServerAddress(serverInfo[0], Integer.parseInt(serverInfo[1]));
		 	
			serverAddressList.add(serverAddress);
		}
	}
}
